// zipfile.cpp
#include <windows.h>
#include "unzip.h"
#pragma comment(lib, "zlibce.lib")
#include "iowin32.h"
#include "zipfile.h"

CZipFile::CZipFile()
  : m_uzFile(NULL)
{
}

CZipFile::~CZipFile()
{
  Close();
}

bool CZipFile::Open(const TCHAR* szFile)
{
  Close();

  if (!szFile)
    return false;

  char szcFile[512];
  int ret = ::WideCharToMultiByte(CP_ACP, 0, szFile, -1, szcFile, 512, NULL, NULL);
  if (ret <= 0)
    return false;

  zlib_filefunc_def ffunc;
  fill_win32_filefunc(&ffunc);
  m_uzFile = unzOpen2(szcFile, &ffunc);

  return (m_uzFile != NULL);
}

void CZipFile::Close()
{
  if (m_uzFile)
  {
    unzCloseCurrentFile(m_uzFile);
    unzClose(m_uzFile);
    m_uzFile = NULL;
  }
}

bool CZipFile::GoToFirstFile()
{
  if (m_uzFile)
  {
    int ret = unzGoToFirstFile(m_uzFile);
    return ret == UNZ_OK;
  }
  else
    return false;
}

bool CZipFile::GoToNextFile()
{
  if (!m_uzFile)
    return false;

  int ret = unzGoToNextFile(m_uzFile);
  return ret == UNZ_OK;
}

bool CZipFile::GoToFile(const TCHAR* szFile)
{
  if (!m_uzFile)
    return false;

  char szcFile[512];
  int ret = ::WideCharToMultiByte(CP_ACP, 0, szFile, -1, szcFile, 512, NULL, NULL);
  if (ret <= 0)
    return false;
  
  ret = unzLocateFile(m_uzFile, szcFile, 2);
  return ret == UNZ_OK;
}

bool CZipFile::GetFileInfo(DWORD& dwSize, TCHAR* sName, size_t nNameLen)
{
  if (!m_uzFile)
    return false;

  unz_file_info file_info;
  int err;
  if (sName != NULL && nNameLen > 0)
  {
    char filename_inzip[512];
    err = unzGetCurrentFileInfo(m_uzFile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
    if (err == UNZ_OK)
    {
      ::MultiByteToWideChar(CP_ACP, 0, filename_inzip, -1, sName, nNameLen);
    }
  }
  else
  {
    err = unzGetCurrentFileInfo(m_uzFile, &file_info, NULL, 0, NULL, 0, NULL, 0);
  }

  if (err == UNZ_OK)
    dwSize = file_info.uncompressed_size;

  return (err == UNZ_OK);
}

bool CZipFile::GetFileData(BYTE* pBuf, DWORD& dwBytes)
{
  if (!m_uzFile)
    return false;

  unz_file_info file_info;
  int err = unzGetCurrentFileInfo(m_uzFile, &file_info, NULL, 0, NULL, 0, NULL, 0);
  if (err != UNZ_OK)
    return false;
  
  if (dwBytes < file_info.uncompressed_size)
    return false;

  err = unzOpenCurrentFile(m_uzFile);
  if (err != UNZ_OK)
    return false;

  DWORD total = 0;
  int cnt;
  do
  {
    cnt = unzReadCurrentFile(m_uzFile, pBuf, dwBytes);
    if (cnt < 0)
    {
      unzCloseCurrentFile(m_uzFile);
      return false;
    }
    total += cnt;
  }
  while (cnt > 0);

  dwBytes = total;

  return true;
}